package com.sijiao.difflog.service.impl;

import com.google.gson.*;
import com.sijiao.difflog.cache.LogDB;
import com.sijiao.difflog.constants.ClassTypeEnum;
import com.sijiao.difflog.constants.OpTypeEnum;
import com.sijiao.difflog.service.ISearchService;
import com.sijiao.difflog.util.BeanUtil;
import com.sijiao.difflog.util.ClassUtil;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class SearchServiceImpl implements ISearchService {
    /**
     * 操作类型    增删改
     * 操作人
     * 操作数据id
     * 操作记录 [
     * {   “id”:1
     * "opType":"新增"
     * "fieldName":"姓名",
     * "filedOriginal":"",
     * "fieldResult":""
     * "items":[
     * ]
     * }
     * ]
     */
    @Override
    public String list() {
        List<String> logJsonList = LogDB.list();
        Random random = new Random();
        int i = random.nextInt(logJsonList.size());
        String json = logJsonList.get(i);

        JsonObject jsonResult = new JsonObject();

        JsonObject jsonObject = (JsonObject) JsonParser.parseString(json);
        String bizName = jsonObject.getAsJsonPrimitive("bizName").getAsString();
        String id = jsonObject.getAsJsonPrimitive("id").getAsString();
        String className = jsonObject.getAsJsonPrimitive("className").getAsString();
        String opType = jsonObject.getAsJsonPrimitive("opType").getAsString();
        JsonObject diffObject = jsonObject.getAsJsonObject("diff");

        if (OpTypeEnum.insert.name().equals(opType)) {
            jsonResult.add("opType", new JsonPrimitive("新增"));
        } else if (OpTypeEnum.delete.name().equals(opType)) {
            jsonResult.add("opType", new JsonPrimitive("删除"));
        } else if (OpTypeEnum.update.name().equals(opType)) {
            jsonResult.add("opType", new JsonPrimitive("修改"));
        }
        jsonResult.add("id", new JsonPrimitive(id));
        JsonArray opArray = new JsonArray();
        jsonResult.add("opDetail", opArray);
        try {
            Class<?> bizClass = SearchServiceImpl.class.getClassLoader().loadClass(className);
            List<Field> classFields = BeanUtil.getClassFields(bizClass);
            for (Field classField : classFields) {
                if (!diffObject.has(classField.getName())) {
                    continue;
                }
                JsonObject opItem = new JsonObject();
                JsonObject fieldObject = diffObject.getAsJsonObject(classField.getName());
                if (fieldObject == null) {
                    continue;
                }
                opItem.add("opType", jsonResult.get("opType").getAsJsonPrimitive());
                opItem.add("fieldName", new JsonPrimitive(LogDB.convertLabel(bizName, className, classField.getName())));
                opArray.add(opItem);

                ClassTypeEnum fieldClassType = ClassUtil.getClassType(classField.getType());
                if (fieldClassType == ClassTypeEnum.primitive || fieldClassType == ClassTypeEnum.string) {
                    opItem.add("fieldOriginal", fieldObject.getAsJsonPrimitive("original"));
                    opItem.add("fieldResult", fieldObject.getAsJsonPrimitive("result"));
                } else if (fieldClassType == ClassTypeEnum.object) {
                    JsonArray jsonArray = new JsonArray();
                    opItem.add("items", jsonArray);
                    opItem.addProperty("id", fieldObject.getAsJsonPrimitive("id").getAsString());
                    for (Map.Entry<String, JsonElement> jsonItemEntry : fieldObject.entrySet()) {
                        if ("id".equals(jsonItemEntry.getKey())) {
                            continue;
                        }
                        JsonObject itemObject = new JsonObject();
                        itemObject.addProperty("fieldName", LogDB.convertLabel(bizName, className, classField.getName() + "." + jsonItemEntry.getKey()));
                        JsonObject valueObject = jsonItemEntry.getValue().getAsJsonObject();
                        if (valueObject.has("result")) {
                            itemObject.addProperty("filedResult", valueObject.get("result").getAsString());
                        }
                        if (valueObject.has("original")) {
                            itemObject.addProperty("filedOriginal", valueObject.get("original").getAsString());
                        }
                        jsonArray.add(itemObject);
                    }
                } else if (fieldClassType == ClassTypeEnum.list) {
                    JsonArray jsonArray = new JsonArray();
                    opItem.add("items", jsonArray);
                    opItem.remove("id");
                    JsonArray insertArray = fieldObject.getAsJsonArray("insert");
                    if (insertArray != null) {
                        JsonObject insertObject = new JsonObject();
                        JsonArray itemArray = new JsonArray();
                        insertObject.addProperty("opType", "新增");
                        insertObject.add("items", itemArray);
                        for (JsonElement jsonElement : insertArray) {
                            if (jsonElement.isJsonPrimitive()) {
                                itemArray.add(jsonElement);
                            } else {
                                JsonObject insertItem = (JsonObject) jsonElement;
                                JsonObject childObject = new JsonObject();
                                JsonArray childArray = new JsonArray();
                                insertObject.addProperty("id", insertItem.getAsJsonPrimitive("id").getAsString());
                                insertObject.add("items", childArray);
                                for (Map.Entry<String, JsonElement> jsonItemEntry : insertItem.entrySet()) {
                                    if ("id".equals(jsonItemEntry.getKey())) {
                                        continue;
                                    }
                                    JsonObject itemObject = new JsonObject();
                                    itemObject.addProperty("fieldName", LogDB.convertLabel(bizName, className, classField.getName() + "." + jsonItemEntry.getKey()));
                                    JsonObject valueObject = jsonItemEntry.getValue().getAsJsonObject();
                                    itemObject.addProperty("filedResult", valueObject.get("result").getAsString());
                                    childArray.add(itemObject);
                                }
                                itemArray.add(childObject);
                            }
                        }
                        jsonArray.add(insertObject);
                    }
                    JsonArray deleteArray = fieldObject.getAsJsonArray("delete");

                    if (deleteArray != null) {
                        JsonObject deleteObject = new JsonObject();
                        JsonArray itemArray = new JsonArray();
                        deleteObject.addProperty("opType", "删除");
                        deleteObject.add("items", itemArray);
                        for (JsonElement jsonElement : deleteArray) {
                            if (jsonElement.isJsonPrimitive()) {
                                itemArray.add(jsonElement);
                            } else {
                                JsonObject deleteItem = (JsonObject) jsonElement;
                                JsonObject childObject = new JsonObject();
                                JsonArray childArray = new JsonArray();
                                childObject.addProperty("id", deleteItem.getAsJsonPrimitive("id").getAsString());
                                childObject.add("items", childArray);
                                for (Map.Entry<String, JsonElement> jsonItemEntry : deleteItem.entrySet()) {
                                    if ("id".equals(jsonItemEntry.getKey())) {
                                        continue;
                                    }
                                    JsonObject itemObject = new JsonObject();
                                    itemObject.addProperty("fieldName", LogDB.convertLabel(bizName, className, classField.getName() + "." + jsonItemEntry.getKey()));
                                    JsonObject valueObject = jsonItemEntry.getValue().getAsJsonObject();
                                    itemObject.addProperty("filedOriginal", valueObject.get("original").getAsString());
                                    childArray.add(itemObject);
                                }
                                itemArray.add(childObject);
                            }
                        }
                        jsonArray.add(deleteObject);
                    }
                    JsonArray updateArray = fieldObject.getAsJsonArray("update");
                    if (updateArray != null) {
                        JsonObject updateObject = new JsonObject();
                        JsonArray itemArray = new JsonArray();
                        updateObject.addProperty("opType", "修改");
                        updateObject.add("items", itemArray);
                        for (JsonElement jsonElement : updateArray) {
                            if (jsonElement.isJsonPrimitive()) {
                                // 基本类型的操作数组数据，不存在修改，只有新增和删除
                            } else {
                                JsonObject updateItem = (JsonObject) jsonElement;
                                JsonObject childObject = new JsonObject();
                                childObject.addProperty("id", updateItem.getAsJsonPrimitive("id").getAsString());
                                JsonArray childArray = new JsonArray();
                                childObject.add("items", childArray);
                                for (Map.Entry<String, JsonElement> jsonItemEntry : updateItem.entrySet()) {
                                    if ("id".equals(jsonItemEntry.getKey())) {
                                        continue;
                                    }
                                    JsonObject itemObject = new JsonObject();
                                    itemObject.addProperty("fieldName", LogDB.convertLabel(bizName, className, classField.getName() + "." + jsonItemEntry.getKey()));
                                    JsonObject valueObject = jsonItemEntry.getValue().getAsJsonObject();
                                    itemObject.addProperty("filedOriginal", valueObject.get("original").getAsString());
                                    itemObject.addProperty("fieldResult", valueObject.get("result").getAsString());
                                    childArray.add(itemObject);
                                }
                                itemArray.add(childObject);
                            }
                        }
                        jsonArray.add(updateObject);
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return jsonResult.toString();
    }

    private JsonObject createFieldOpInfo(JsonObject jsonResult, JsonObject jsonObject, String bizName, String id, String className, Field classField) {
        JsonObject opItem = new JsonObject();
        JsonObject fieldObject = jsonObject.getAsJsonObject(classField.getName());
        if (fieldObject == null) {
            return null;
        }
        opItem.add("id", new JsonPrimitive(id));
        opItem.add("opType", jsonResult.get("opType").getAsJsonPrimitive());
        opItem.add("fieldName", new JsonPrimitive(LogDB.convertLabel(bizName, className, classField.getName())));
        opItem.add("filedOriginal", fieldObject.getAsJsonPrimitive("original"));
        opItem.add("fieldResult", fieldObject.getAsJsonPrimitive("result"));
        return opItem;
    }
}
